(ns web.json-rpc
  (:use clojure.tools.logging
        web.app)
  (:require clojure.data.json))

(defn bind-apis [apis]
  (fn [method params]
    (apply
      (get apis method (fn [& params] (throw (Exception. (str "Unkown method " method)))))
      params)))

(defn- error-response [id e]
  (error e e)
  {"result" nil
   "error" (.getMessage e)
   "id" id})

(defn json-rpc-call [api-call {method "method" params "params" id "id"}]
  (try
    {"result" (api-call method params)
     "error" nil
     "id" id}
    (catch Exception e
      (error-response id e))
    (catch AssertionError e
      (error-response id e))))

(defn json-rpc
  ([{body :body :as request} api-call]
    ; TODO: logging input, logging performance
    (binding [*app-cookie* (:cookies request)]
      (let [input-json (org.apache.commons.io.IOUtils/toString body "utf-8")
            input (clojure.data.json/read-str input-json)
            output (json-rpc-call api-call input)
            output-json (clojure.data.json/write-str output)]
        {:headers {"Content-Type" "application/json-rpc; charset=UTF-8"}
         :body output-json})))
  ([api-call]
    #(json-rpc % api-call)))
